package com.mew.chess.core.game.bjl.game;

import com.mew.chess.core.common.utils.ChessGameUtil;
import com.mew.chess.core.common.utils.RobotNumberUtils;
import com.mew.chess.core.game.bjl.game.common.BjlBetType;
import com.mew.chess.core.game.bjl.game.common.BjlConstantValue;
import com.mew.chess.core.game.bjl.game.common.BjlLinkType;
import com.mew.chess.core.game.bjl.game.common.BjlResultBO;
import com.mew.chess.core.game.bjl.game.message.*;
import com.mew.common.enm.UserType;
import com.mew.common.rest.bo.GameSession;
import lombok.Data;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;

@Data
public class BjlRoomManager {
    private long ino;//局号

    //基础信息
    private final int gameId;
    private final int roomId;
    private int minGoldNumber;
    private String betStrs;
    private int[] betArrays;
    private long maxBetLimit;
    //Schedule
    private BjlScheduleManager bjlScheduleManager;

    //在线玩家
    private int robotNumber;//机器人人数
    private final ConcurrentMap<Long, GameSession> onlineUser = new ConcurrentHashMap<>(16);//真人玩家session
    private final ConcurrentMap<Long, UserMessage> playerList = new ConcurrentHashMap<>(16);//在线玩家
    private Map<Long,UserMessage> bigRList = new HashMap<>();//大玩家;

    //牌库
    private List<Integer> cardLib=new ArrayList<>(320);

    private LongAdder totalNumber=new LongAdder();
    private Map<Integer,Long> typeNumber=new ConcurrentHashMap<>();//各个区域压注

    //游戏结果
    private BjlResultBO bjlResult = new BjlResultBO();
    //历史记录
    private List<HistoryMessage> historyList=new ArrayList<>();

    //消息体
    private PushShuffleCardMessage pushShuffleCardMessage = new PushShuffleCardMessage();
    private PushDealCardMessage pushDealCardMessage = new PushDealCardMessage();
    private PushStartBetMessage pushStartBetMessage = new PushStartBetMessage();
    private PushOpenCardMessage pushOpenCardMessage = new PushOpenCardMessage();

    //阶段信息
    private int linkType;
    private long startTime;
    private int ruleTime;

    private boolean needInit=false;//是否想需要初始数据

    public BjlRoomManager(int gameId, int roomId) {
        this.gameId = gameId;
        this.roomId = roomId;
    }

    /**
     * 检查游戏是否启动
     * @return
     */
    public boolean checkIsNoStart() {
        return bjlScheduleManager.getFlag().get();
    }

    /**
     * 启动游戏
     */
    public void startGame(){
        bjlScheduleManager.start();
    }
    /**
     * 停止游戏
     */
    public void stopGame(){
        bjlScheduleManager.stop();
        this.linkType = BjlLinkType.Prepare.code();
        this.ruleTime = BjlConstantValue.PAYMENT_TIME;
        this.startTime = 0;

        this.needInit=true;
        this.initInfo();
    }

    /**
     * 退出游戏
     * @param userId
     */
    public void exitRoom(long userId){
        onlineUser.remove(userId);
        UserMessage user = getPlayer(userId);
        if(user.getBetRecord().size()==0){
            playerList.remove(userId);
        }
    }

    /**
     * 注册玩家
     * @param session
     */
    public UserMessage registerOnlineUser(GameSession session){
        onlineUser.put(session.getUserId(), session);
        UserMessage userVO = getPlayer(session.getUserId());
        userVO = null==userVO?new UserMessage():userVO;
        userVO.setGameSession(session);
        playerList.put(session.getUserId(), userVO);
        return userVO;
    }
    /**
     * 获取玩家
     * @param userId
     * @return
     */
    public UserMessage getPlayer(long userId){
        return playerList.get(userId);
    }

    /**
     * 移除玩家
     * @param userId
     */
    public void clearOnlineUser(long userId){
        onlineUser.remove(userId);
        playerList.remove(userId);
    }

    /**
     * 阶段改变
     * @param linkType
     * @param ruleTime
     */
    public void changeLink(int linkType,int ruleTime){
        this.linkType=linkType;
        this.startTime=System.currentTimeMillis();
        this.ruleTime=ruleTime;
    }

    /**
     * 添加历史记录
     */
    public void addHistory(){
        HistoryMessage historyMessage=new HistoryMessage();
        List<Integer> winList = bjlResult.getWinList();
        historyMessage.setWinType(winList.get(0));
        if(winList.contains(BjlBetType.BankerTwo.code())){
            historyMessage.setBankerTwo(1);
        }
        if(winList.contains(BjlBetType.IdleTwo.code())){
            historyMessage.setIdleTwo(1);
        }
        if(historyList.size()==66){
            historyList.remove(0);
        }
        historyList.add(historyMessage);
    }

    /**
     * 是否是大玩家
     * @param userId
     * @return
     */
    public boolean isBigPlayer(long userId){
       return this.bigRList.keySet().contains(userId);
    }

    /**
     * 初始化信息
     */
    public void initInfo(){
        if(needInit){
            examineRobot();
            refreshBigPlayer();
            needInit=false;
            totalNumber.reset();
            typeNumber.clear();
            bjlResult.clear();
            for (UserMessage user : playerList.values()) {
                user.clear();
            }

        }
    }

    /**
     * 检查机器人
     */
    private void examineRobot(){
        //剔除不合规机器人
        this.playerList.values().stream().forEach(u->{
            if(u.getUserType()== UserType.Robot.code()&&(u.getPlayTimes()<=0||u.getGoldNumber()<this.getMinGoldNumber())){
                this.playerList.remove(u.getUserId());
            }
        });
        //从新获取机器人数量
        int robotNum= RobotNumberUtils.robotNumber(BjlConstantValue.ROBOT_INIT_NUMBER);
        if(robotNum<this.playerList.size()){
            int delNum=this.playerList.size()-robotNum;
            for (UserMessage u : this.playerList.values()) {
                if(u.getUserType()==UserType.Robot.code()){
                    this.playerList.remove(u.getUserId());
                    if(delNum--==0){
                        return;
                    }
                }
            }
        }else if(robotNum>this.playerList.size()){
            for (int i = 0; i < robotNum-this.playerList.size(); i++) {
                UserMessage robot = UserMessage.buildBjlRobotUserMessage(this.minGoldNumber, BjlConstantValue.ROBOT_GOLD_SEC);
                this.playerList.put(robot.getUserId(),robot);
            }
        }
        this.robotNumber=(int)this.playerList.values().stream().filter(u->u.getUserType()==UserType.Robot.code()).count();
    }

    /**
     * 刷新大玩家
     */
    private void refreshBigPlayer(){
        List<UserMessage> list = this.playerList.values().stream().collect(Collectors.toList());
        Collections.sort(list,(u1,u2)->Long.compare(u2.getPayment(),u1.getPayment()));
        this.bigRList.clear();
        for (UserMessage userMessage : list) {
            bigRList.put(userMessage.getUserId(),userMessage);
            if(this.bigRList.size()==BjlConstantValue.BIG_PLAYER_NUMBER){
                return;
            }
        }
    }
    public PushBetMessage bets(BetRecordMessage[] chipBets){
        PushBetMessage message=new PushBetMessage();
        message.setChipBets(chipBets);
        for (BetRecordMessage chipBet : chipBets) {
            bet(chipBet.getBetType(),chipBet.getBetNumber());
        }
        message.setTotalNumber(totalNumber.longValue());
        message.setTypeNumber(typeNumber);
        return message;
    }
    public void bet(int betType,long betNumber){
        this.totalNumber.add(betNumber);
        typeNumber.put(betType,null==typeNumber.get(betType)?betNumber:betNumber+typeNumber.get(betType));
    }
    public void cancelBet(int betType,long betNumber){
        this.totalNumber.add(betNumber*-1);
        typeNumber.put(betType,typeNumber.get(betType)-betNumber);
    }
}

